import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.geom.Rectangle;
import flash.geom.Point;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.display.Sprite;
import flash.ui.Keyboard;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
import flash.filters.GlowFilter;
import haxe.FastList;
import flash.events.MouseEvent;
import flash.net.SharedObject;
import flash.Lib;
import haxe.Log;

import flash.utils.Timer;
import haxe.Timer;
import flash.events.Event;
import flash.display.MovieClip;
import flash.media.SoundChannel;


import Images; 
import Sounds; 
import MovieClips;
import Blob;
import Scene;
import TextArea;
import InstructionPage;
import AchievementPage;
import CreditsPage;
import OptionsPage;
import SoundPlayer;
import PauseMenu;
import Kongregate;
import Logo;
import CustomSprite;

class Main extends Sprite{
private var ground : Int;
private var currentLevel : Int;
private var Scenes : Array<Scene>;
//Because the levels are so similiar i can do this. It's probably be to have a class for each level that inherents from the scence. 
private var Level1 : Scene;

private var State : String;
private var savedData:SharedObject;
private var ContinueGameButton:Sprite;
private var AchievementButton:Sprite;
private var StartGameButton:Sprite;
private var MainMenuButton:Sprite;
private var InstructionsButton:Sprite;
private var CreditsButton:Sprite;
private var OptionsButton:Sprite;
private var Title:TextField;
private var myLogo : Logo;
private var myKongLogo : KongLogo;

private var label1:TextField;
private var Zombie:Sprite;
var myTimer:Timer;
var music:BackgroundMusic;            
private var player:SoundPlayer;
public var preloader:PreloaderHost;
private var BackgroundImage : Sprite;
public var Instruction : InstructionPage;
public var AchievementMenu: AchievementPage;
public var Credit: CreditsPage;
public var OptionsMenu : OptionsPage;
public var mKeyDown:Array<Bool>;
var pausePosition:Float;
//             music.play();
var volume:Bool;
var sound:Bool;
var framerate:Int;

var kongVar : CKongregate;

var RecievedAchievements:Achievements;
public function new(){
haxe.remoting.AMFConnection.registerClassAlias("FastListAlias",FastList);
haxe.remoting.AMFConnection.registerClassAlias("AchievementsAlias",Achievements);

super();
Scenes = [];
RecievedAchievements = new Achievements();
getLevelData();

//inPostion,inMoveSpeed,inJumpSpeed,inAttackSpeed,inHealth:Int
initLevels();

//Add Main to Current Flash
flash.Lib.current.addChild(this);
//Create Menu (own Class?)
Title = new TextField();
    
  Title.x = 55; Title.y = 20;
  Title.width = Constants.flashWidth-100; Title.height = Constants.flashHeight;
  Title.multiline = true;
  var myFormat:TextFormat = new TextFormat();
  myFormat.size = 25;
  myFormat.align = TextFormatAlign.CENTER;
  Title.defaultTextFormat = myFormat;
  
  Title.htmlText = "<font color='#FFFFFF'>The</font>  Game";

//It seems like there should be a better way to add a bitmap to a Sprite than filling the background with the bitmap. But this works.
StartGameButton = new Sprite();
StartGameButton.graphics.beginFill(0x000000);
StartGameButton.graphics.lineStyle(1,0xFFFFFF);
StartGameButton.graphics.drawRect(0, 0, 125 ,125);
var StartGameButtonText = new TextField();
StartGameButtonText.htmlText = "<font size='20' color ='#FFFFFF'>Start Game</font>";
StartGameButtonText.x = 10;
StartGameButtonText.y = 40;
StartGameButtonText.selectable = false;
StartGameButtonText.mouseEnabled = false;
StartGameButton.addChild(StartGameButtonText);
StartGameButton.x = 95;
StartGameButton.y = 75;

StartGameButton.buttonMode = true;
StartGameButton.addEventListener(MouseEvent.CLICK, onStartGameButtonClick);

ContinueGameButton = new Sprite();

ContinueGameButton.graphics.beginFill(0xFFFFFF);
ContinueGameButton.graphics.lineStyle(1,0x000000);
ContinueGameButton.graphics.drawRect(0, 0, 125 ,125);
var ContinueGameButtonText = new TextField();
ContinueGameButtonText.htmlText = "<font size='20' color ='#000000'>Continue\nGame</font>";
ContinueGameButtonText.x = 15;
ContinueGameButtonText.y = 30;
ContinueGameButtonText.selectable = false;
ContinueGameButtonText.mouseEnabled = false;
ContinueGameButton.addChild(ContinueGameButtonText);
ContinueGameButton.x = 420;
ContinueGameButton.y = 75;
ContinueGameButton.buttonMode = true;
ContinueGameButton.addEventListener(MouseEvent.CLICK, onContinueGameButtonClick);


AchievementButton = new Sprite();

AchievementButton.graphics.beginFill(0x000000);
AchievementButton.graphics.lineStyle(1,0xFFFFFF);
AchievementButton.graphics.drawRect(0, 0, 125 ,125);
var AchievementButtonText = new TextField();
AchievementButtonText.htmlText = "<font size='16' color ='#FFFFFF'>Achievements</font>";
AchievementButtonText.x = 10;
AchievementButtonText.y = 45;
AchievementButtonText.selectable = false;
AchievementButtonText.mouseEnabled = false;
AchievementButton.addChild(AchievementButtonText);
AchievementButton.x = 45;
AchievementButton.y = 250;
AchievementButton.buttonMode = true;
AchievementButton.addEventListener(MouseEvent.CLICK, onAchievementButtonClick);

AchievementMenu = new AchievementPage(RecievedAchievements);
AchievementMenu.addEventListener("Back",onAchievementBack);

InstructionsButton = new Sprite();
InstructionsButton.graphics.beginBitmapFill(new Instructions());
InstructionsButton.graphics.drawRect(0, 0, 250 ,48);
InstructionsButton.x = 195;
InstructionsButton.y = 215;

InstructionsButton.buttonMode = true;
InstructionsButton.addEventListener(MouseEvent.CLICK, onInstrutionsButtonClick);

Instruction = new InstructionPage();
Instruction.addEventListener("Back",onInstrutionsBack);

CreditsButton = new Sprite();
CreditsButton.graphics.beginFill(0xFFFFFF);
CreditsButton.graphics.lineStyle(1,0x000000);
CreditsButton.graphics.drawRect(0, 0, 125 ,125);
var CreditsButtonText = new TextField();
CreditsButtonText.htmlText = "<font size='20' color ='#000000'>Credits</font>";
CreditsButtonText.selectable = false;
CreditsButtonText.mouseEnabled = false;
CreditsButtonText.x = 25;
CreditsButtonText.y = 40;
CreditsButton.addChild(CreditsButtonText);
CreditsButton.x = 450;
CreditsButton.y = 250;

CreditsButton.buttonMode = true;
CreditsButton.addEventListener(MouseEvent.CLICK, onCreditsButtonClick);

Credit = new CreditsPage();
Credit.addEventListener("Back",onCreditsBack);

OptionsButton = new Sprite();

OptionsButton.graphics.beginFill(0xFFFFFF);
OptionsButton.graphics.lineStyle(1,0x000000);
OptionsButton.graphics.drawRect(62, 0, 62 ,125);
OptionsButton.graphics.beginFill(0x000000);
OptionsButton.graphics.lineStyle(1,0xFFFFFF);
OptionsButton.graphics.drawRect(0, 0, 62 ,125);
var OptionsButtonText = new TextField();
OptionsButtonText.htmlText = "<font size='20' color ='#FFFFFF'>Opti</font><font size='20' color ='#000000'>ons</font>";
OptionsButtonText.selectable = false;
OptionsButtonText.mouseEnabled = false;
OptionsButtonText.x = 22;
OptionsButtonText.y = 40;
OptionsButton.addChild(OptionsButtonText);
OptionsButton.x = 258;
OptionsButton.y = 250;

OptionsButton.buttonMode = true;
OptionsButton.addEventListener(MouseEvent.CLICK, onOptionsButtonClick);

OptionsMenu = new OptionsPage();
OptionsMenu.addEventListener("Back",onOptionsMenuBack);
OptionsMenu.addEventListener("ResetSavedData",onOptionsMenuResetSavedData);
OptionsMenu.addEventListener("VolumeToggle",onOptionsMenuVolumeToggle);
OptionsMenu.addEventListener("SoundEffectsToggle",onOptionsMenuSoundEffectsToggle);
//this.addEventListener(Event.ENTER_FRAME, OnEnter);
myTimer = new Timer(12);
  myTimer.addEventListener("timer", OnEnter);
  myTimer.start();

  label1 = new TextField();
  label1.x = 0; label1.y = 0;
  label1.width = Constants.flashWidth; label1.height = 100;
  label1.autoSize = TextFieldAutoSize.CENTER;

Zombie = new Sprite();
Zombie.graphics.beginBitmapFill(new Menu());
Zombie.graphics.drawRect(0, 0, 46,52);
Zombie.x = 300;
Zombie.y = 75;

MainMenuButton  = new Sprite();
MainMenuButton.graphics.beginBitmapFill(new MainMenu());
MainMenuButton.graphics.drawRect(0, 0, 250 ,48);
MainMenuButton.x = 200;
MainMenuButton.y = 135;
MainMenuButton.buttonMode = true;
MainMenuButton.addEventListener(MouseEvent.CLICK, onMainMenuButtonClick);

//The State Will determine whether to load a level, or show Main Menu, or whatever.  Used in the OnEnterEvent.
State = "InitLoad";
//State = "LoadMainMenu";
music = new BackgroundMusic();
preloader = new PreloaderHost();
BackgroundImage = new Sprite();
BackgroundImage.graphics.beginFill(0x000000);
//Grid.graphics.drawRect(0, 0,620-150,472);
BackgroundImage.graphics.drawRect(0, 0, (0.5 *(Constants.flashWidth)),Constants.flashHeight);
BackgroundImage.graphics.beginFill(0xFFFFFF);
BackgroundImage.graphics.drawRect((0.5 *(Constants.flashWidth)), 0,(0.5) *(Constants.flashWidth),Constants.flashHeight);
BackgroundImage.graphics.endFill();
player = new SoundPlayer(music);
player.play(pausePosition);

mKeyDown = [];
stage.addEventListener(KeyboardEvent.KEY_DOWN, OnKeyDown );
stage.addEventListener(KeyboardEvent.KEY_UP, OnKeyUp );
volume = true;
sound = true;
myLogo = new Logo();
addChild(myLogo);
myKongLogo = new KongLogo();
addChild(myKongLogo);
try
{
kongVar = new CKongregate();
}
catch (msg:Dynamic)
{
}

//preloader.addEventListener(Event.ENTER_FRAME, OnMovieEnter);
}

function loadMenu()
{
  addChild(BackgroundImage);
  addChild(Title);
  addChild(StartGameButton);
  addChild(ContinueGameButton);
  addChild(AchievementButton);
  //addChild(InstructionsButton);
  addChild(CreditsButton);
  addChild(OptionsButton);
}
function removeMenu()
{
  removeChild(Title);
  removeChild(StartGameButton);
  removeChild(ContinueGameButton);
  removeChild(AchievementButton);
  removeChild(BackgroundImage);
  //removeChild(InstructionsButton);
  removeChild(CreditsButton);
  removeChild(OptionsButton);
}

//Change to stat Menu
function loadTryAgainMenu(text:String)
{
  addChild(label1);
  label1.htmlText = "<font size='15'>" + text + "</font>";
  addChild(MainMenuButton);
  addChild(Zombie);
  player.stop();
}
function removeTryAgainMenu()
{
 removeChild(label1);
 removeChild(MainMenuButton);
 removeChild(Zombie);
}
function initLevels()
{

//Postion, MoveSpeed, JumpSpeed, AttackSpeed, Health, Bitmap)

}

function OnEnter(e:flash.events.Event)
{
if(State == "LoadMainMenu")
{
 loadMenu();
 State = "MainMenu";
}
if(State == "MainMenu" )
   {
      if(!volume)
      {
	 pausePosition = player.getPosition();
         player.stop();
         
      }
      else
      {
        player.play(pausePosition);
      }
     return;
   }
if(State == "TryAgain")
  {
    AnimateZombie();
    return;
  }
if(State == "InitLoad")
  {
    myKongLogo.start();
    myLogo.start();
    State = "InitLoading";
  }
if(State == "InitLoading")
   { 
    //Always Playing. Possible error with swfmill
    //Skipping for now.
      if(!myKongLogo.play())
     {
       State = "LoadingLogo";
     }

   }
if(State == "LoadingLogo")
  {
     if(!myLogo.play())
     {
       State = "LoadMainMenu";
     }
  }
if(State == "StartGame")
   {
    //player.play(pausePosition);
    loadCurrentLevel(false);
   }
if(State == "ContinueGame")
   {
    //player.play(pausePosition);
    loadCurrentLevel(true);
   }
if(State == "Playing")
   {
    if(Scenes[currentLevel-1] != null)
    {
      if(Scenes[currentLevel-1].running)
      {
      if(!volume)
      {
	 pausePosition = player.getPosition();
         player.stop();
         
      }
      else
      {
        player.play(pausePosition);
      }
      return;
      }
      else
      { 
      return;
      } 
        
    }
    loadCurrentLevel(true);
   }
// try
// {
// //             var req:flash.net.URLRequest = new flash.net.URLRequest("http://av.adobe.com/podcast/csbu_dev_podcast_epi_2.mp3");
// //             
// //             Sound.load(req);
// var music = new BackgroundMusic();            
//             music.play();
// }
// catch (err:flash.Error)
// {
// trace(err.message);
// }


}
public function AnimateZombie()
{
var randomNumber = Std.random(24);
if(randomNumber == 1)
  Zombie.x = Zombie.x + 5;
if(randomNumber == 2)
  Zombie.x = Zombie.x - 5;

}

//Loads Level based on Current Level
public function loadCurrentLevel(inContinue:Bool) : Bool
{
  currentLevel = 1;
  Level1 = new Scene(new Background());
  Scenes[currentLevel-1] = Level1;




  State = "Playing";
  //Level1.Load();
  Scenes[currentLevel-1].RecievedAchievements = RecievedAchievements;
  Scenes[currentLevel-1].kongVar = kongVar;
  Scenes[currentLevel-1].Load(volume,sound,inContinue);

  Scenes[currentLevel-1].pauseMenu.renderVolume(volume);
  Scenes[currentLevel-1].pauseMenu.renderSoundEffects(sound);
  Scenes[currentLevel-1].addEventListener("VolumeToggle",onSceneVolumeToggle);
  Scenes[currentLevel-1].addEventListener("SoundEffectsToggle",onSceneSoundEffectsToggle);
  Scenes[currentLevel-1].addEventListener("MainMenuBack",onSceneMainMenu);
  Scenes[currentLevel-1].addEventListener("LevelRetry",onSceneLevelRetry);
  Scenes[currentLevel-1].addEventListener("LevelReturn",onSceneLevelReturn);
  return true;
}


public function getLevelData()
{
  currentLevel = 1;
  pausePosition = 0;
  //Load Save Data
  savedData = SharedObject.getLocal("AchievementsData");
  if(savedData.data.Achievements != null)
  {
    RecievedAchievements = savedData.data.Achievements;
    //pausePosition = savedData.data.SoundPosition;
  }
}
public function removeClip(preloader)
{
 removeChild(preloader);
}
private function onStartGameButtonClick(event:MouseEvent) {
currentLevel = 1;
pausePosition = 0;
removeMenu();
State = "StartGame";
}

private function onContinueGameButtonClick(event:MouseEvent) {


removeMenu();
State = "ContinueGame";
}
private function onAchievementButtonClick(event:MouseEvent) {
removeMenu();
AchievementMenu.RecievedAchievements = RecievedAchievements;
AchievementMenu.redraw();
addChild(AchievementMenu);
}

private function onMainMenuButtonClick(event:MouseEvent) {
removeTryAgainMenu();
State = "LoadMainMenu";
}
private function onInstrutionsButtonClick(event:MouseEvent) {
removeMenu();
addChild(Instruction);
}

private function onCreditsButtonClick(event:MouseEvent) {
removeMenu();
addChild(Credit);
}

private function onOptionsButtonClick(event:MouseEvent) {
removeMenu();
addChild(OptionsMenu);
OptionsMenu.renderVolume(volume);
OptionsMenu.renderSoundEffects(sound);
}

private function onInstrutionsBack(event:InstructionPageEvent)
{
removeChild(Instruction);
loadMenu();
}

private function onOptionsMenuBack(event:OptionsPageEvent)
{
removeChild(OptionsMenu);
loadMenu();
}
private function onOptionsMenuVolumeToggle(event:OptionsPageEvent)
{
volume = !volume;
OptionsMenu.renderVolume(volume);
}
private function onOptionsMenuSoundEffectsToggle(event:OptionsPageEvent)
{
sound = !sound;
OptionsMenu.renderSoundEffects(sound);
}

private function onSceneVolumeToggle(event:PauseMenuEvent)
{
volume = !volume;
Scenes[currentLevel-1].volume = volume;
Scenes[currentLevel-1].pauseMenu.renderVolume(volume);
}
private function onSceneSoundEffectsToggle(event:PauseMenuEvent)
{
sound = !sound;
Scenes[currentLevel-1].sound = sound;
Scenes[currentLevel-1].pauseMenu.renderSoundEffects(sound);
}

public function OnKeyUp (event:KeyboardEvent)
    {
      mKeyDown[event.keyCode] = false;
      //lastUp = event.keyCode;
    }

public function OnKeyDown(event:KeyboardEvent)
   {
      // When a key is held down, multiple KeyDown events are generated.
      // This check means we only pick up the first one.
      if (!mKeyDown[event.keyCode])
      {
         // Store for use in game
         mKeyDown[event.keyCode] = true;
	  //I do this here, because if they hold down P,
	 // it won't pause and unpause constantly.
	  if(mKeyDown[ 77 ] == true)
	  {
	    volume = !volume;
	    Scenes[currentLevel-1].volume = volume;
	    Scenes[currentLevel-1].pauseMenu.renderVolume(volume);
	  }
      }
  }

private function onSceneLevelRetry(event:Event)
{
  Scenes[currentLevel-1].unLoad();
  loadCurrentLevel(false);
}



private function onSceneMainMenu(event:PauseMenuEvent)
{
  Scenes[currentLevel-1].unLoad();
  State = "InitLoad";
}

private function onSceneLevelReturn(event:Event)
{
  Scenes[currentLevel-1].unLoad();
  State = "InitLoad";
}
private function onOptionsMenuResetSavedData(event:OptionsPageEvent)
{
      	var achievementsData = SharedObject.getLocal("AchievementsData");
	achievementsData.data.Achievements = new Achievements();
	achievementsData.flush();
      getLevelData();
      pausePosition = 0;
      currentLevel = 1;
}
private function onCreditsBack(event:CreditsPageEvent)
{
removeChild(Credit);
loadMenu();
}
private function onAchievementBack(event:AchievementPageEvent)
{
  removeChild(AchievementMenu);
  loadMenu();
}

//Couldn't get preloader to work.
	    static function onEnterFrame(event : Event)
	    {
	        Log.trace("Downloaded " + Lib.current.root.loaderInfo.bytesLoaded + " of " + Lib.current.root.loaderInfo.bytesTotal + " bytes");
	 
	        if (Lib.current.root.loaderInfo.bytesLoaded >= Lib.current.root.loaderInfo.bytesTotal)
	        {
	            Lib.current.root.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
	            Log.trace("Preloading finished");
	            Lib.current.gotoAndStop("start");
                  // new Images();
	          var mainInstance:Main = new Main();
	        }
	    }

    static function main() {
// Log.trace("Starting preloader");
  //Lib.current.roott.addEventListener(Event.ENTER_FRAME, onEnterFrame);
try
{
 new Main();
}
catch (err:flash.Error)
{
trace(err.message);

}
      // Create the request object...
//       var loader = new flash.display.Loader();
//       // When the image is ready, instanciate the game class...
//       loader.contentLoaderInfo.addEventListener(flash.events.Event.COMPLETE,
//           function(_) { new Main(untyped loader.content.bitmapData); });
//       // Fire off the request and wait...
//       loader.load(new flash.net.URLRequest("img/file.gif"));
        //new Main();    
      
	
    }
}